///
/// 用位示图管理磁盘存储空间
///
#include <iostream>
#include <iomanip>
#include <bitset>
using namespace std;
const int cylinderNum = 8;                               // 柱面数量
const int trackNum = 2;                                  // 磁道数量
const int recordNum = 4;                                 // 物理记录数量
const int blockNum = cylinderNum * trackNum * recordNum; // 块数量
bitset<blockNum> diskBitMap;                             // 存储空间位示图

void allocateDiskSpace();
void releaseDiskSpace();
void displayBitMap();

int main()
{
    char choice;
    do
    {
        cout << "Would you like to allocate disk space or release disk space? (A/R)" << endl;
        cin >> choice;
        switch (choice)
        {
        case 'A':
            allocateDiskSpace();
            break;
        case 'R':
            releaseDiskSpace();
            break;
        default:
            cout << "Invalid input, please try again." << endl;
        }
        displayBitMap();
        cout << "Would you like to continue managing disk space? (Y/N)" << endl;
        cin >> choice;
    } while (choice == 'Y' || choice == 'y');
    cout << "Exiting disk space management program..." << endl;
    return 0;
}

void allocateDiskSpace()
{
    int byteNum, bitNum, address;
    bool allocated = false;
    for (byteNum = 0; byteNum < diskBitMap.size() / 8; byteNum++)
    { // 遍历字节
        for (bitNum = 0; bitNum < 8; bitNum++)
        { // 遍历位
            if (!diskBitMap[byteNum * 8 + bitNum])
            {                                   // 找到空闲块
                address = byteNum * 8 + bitNum; // 计算物理地址
                diskBitMap[address] = true;     // 设置为已占用
                cout << "Allocated block at physical address: Cylinder " << address / (trackNum * recordNum)
                     << ", Track " << (address % (trackNum * recordNum)) / recordNum
                     << ", Record " << address % recordNum << endl;
                allocated = true;
                break;
            }
        }
        if (allocated)
        { // 如果已分配
            break;
        }
    }
    if (!allocated)
    {
        cout << "Sorry, there is no free space available for allocation." << endl;
    }
}

void releaseDiskSpace()
{
    int cylinderNum, trackNum, recordNum, address;
    cout << "Please enter the physical address of the block you want to release:" << endl;
    cout << "Cylinder number: ";
    cin >> cylinderNum;
    cout << "Track number: ";
    cin >> trackNum;
    cout << "Record number: ";
    cin >> recordNum;
    // 判断输入是否合法
    if (cylinderNum < 0 || cylinderNum >= ::cylinderNum || trackNum < 0 || trackNum >= ::trackNum || recordNum < 0 || recordNum >= ::recordNum)
    {
        cout << "Invalid physical address, please try again." << endl;
        return;
    }
    address = cylinderNum * trackNum + recordNum;
    diskBitMap[address] = false; // 设置为空闲
    cout << "Released block at physical address: Byte " << address / 8
         << ", Bit " << address % 8 << endl;
}

void displayBitMap()
{
    cout << "Disk Space Bit Map:" << endl;
    for (int i = 0; i < diskBitMap.size(); i++)
    {
        if (i % 8 == 0)
        { // 每8位分一组输出
            cout << setw(3) << i / 8 << ": ";
        }
        cout << diskBitMap[i];
        if (i % recordNum == recordNum - 1)
        { // 每个物理记录后面添加一个空格
            cout << ' ';
        }
        if (i % (trackNum * recordNum) == trackNum * recordNum - 1)
        { // 每个磁道后面换行
            cout << endl;
        }
    }
    cout << endl;
}
